
#import <QuartzCore/QuartzCore.h>
#import "SlidingView.h"

@interface SlidingView ()
{
    BOOL _isShown;
    NSLayoutConstraint *_positionConstraint;
    float _dragButtonLength;
}
@property (nonatomic, assign) CGFloat sliderLength;
@property (nonatomic, strong) UIView *settingsOutsideView;

@end

@implementation SlidingView

-(SlidingView *)initWithLength:(CGFloat)length
{
    self = [super init];
    if (self)
    {
        _sliderLength = length;
        _animationDuration = 0.3;
        _isShown = NO;
        
        [self setTranslatesAutoresizingMaskIntoConstraints:NO];
        
        UIImage *dragImage = [UIImage imageNamed:@"flik"];
        _dragButtonLength = dragImage.size.width;
        _dragButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_dragButton setTranslatesAutoresizingMaskIntoConstraints:NO];
        [_dragButton setBackgroundImage:dragImage forState: UIControlStateNormal];
        [_dragButton setBackgroundImage:dragImage forState: UIControlStateHighlighted];
        [_dragButton addTarget:self action:@selector(dragButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
        [_dragButton addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDragButton:)]];
        [self addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDragButton:)]];
        
        _settingsOutsideView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 1024)];
        _settingsOutsideView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:.2];
        _settingsOutsideView.alpha = 0.0;
        _settingsOutsideView.userInteractionEnabled = YES;
        
        [_settingsOutsideView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(outsideTapped:)]];
        
    }
    return self;
}

-(void)setControllerSubview:(UIView *)subview
{
    [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

    subview.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:subview];
    
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self,subview);
    
    NSString *constraint = [NSString stringWithFormat: @"|[subview]|"];
    [self addConstraintText:constraint toView:self withDictionary:viewsDictionary];

    constraint = [NSString stringWithFormat: @"V:|[subview]|"];
    [self addConstraintText:constraint toView:self withDictionary:viewsDictionary];
}

-(void)addConstraintText:(NSString *)text toView:(UIView *)view withDictionary:(NSDictionary *)dict
{
    NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:text options:0 metrics:nil views:dict];
    [view addConstraints:constraints];
}

-(void)attachToView:(UIView *)parentView
{
    [self removeConstraints: self.constraints];
    [_dragButton removeConstraints:_dragButton.constraints];
    
    [parentView addSubview: self];
    [parentView addSubview: _dragButton];
    [parentView addSubview:_settingsOutsideView];
    
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self, _dragButton);
    NSString * constraint1;
    
    constraint1 = [NSString stringWithFormat: @"V:|-(%d)-[self]-(%d)-|", 10, 10];
    [self addConstraintText:constraint1 toView:parentView withDictionary:viewsDictionary];
    
    constraint1 = [NSString stringWithFormat: @"[_dragButton(%f)][self(%f)]", _dragButtonLength, _sliderLength];
    [self addConstraintText:constraint1 toView:parentView withDictionary:viewsDictionary];
    
    _positionConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:parentView attribute:NSLayoutAttributeRight multiplier:1.0 constant:_sliderLength];
    [parentView addConstraint:_positionConstraint];
    [parentView addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:0 toItem:_dragButton attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
    [parentView addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:0 toItem:_dragButton attribute:NSLayoutAttributeLeft multiplier:1.0 constant:_dragButtonLength - 1.0]];
    
    [parentView bringSubviewToFront:_settingsOutsideView];
    [parentView bringSubviewToFront:self];
    [parentView bringSubviewToFront:_dragButton];
}

#pragma mark - Actions

-(void)dragButtonPressed:(UIButton *)button
{
    if (_isShown) {
        [self hideSliderContentWithDuration:_animationDuration];
    } else {
        [self showSliderContentWithDuration:_animationDuration];
    }
}

-(void)showSliderTab {
    [UIView animateWithDuration:0.3 delay:1 options:UIViewAnimationOptionCurveLinear animations:^
     {
         _positionConstraint.constant = _sliderLength;
         [self.superview layoutIfNeeded];
     } completion:nil];
}

-(void)hideSliderTab {
    [UIView animateWithDuration:0.05 delay:0 options:UIViewAnimationOptionCurveLinear animations:^
     {
         _positionConstraint.constant = _sliderLength + _dragButtonLength;
         [self.superview layoutIfNeeded];
     } completion:nil];
}

-(void)showSliderContent
{
    if (!_isShown) {
        [self showSliderContentWithDuration:_animationDuration];
    }
}

-(void)hideSliderContent
{
    if (_isShown) {
        [self hideSliderContentWithDuration:_animationDuration];
    }
}

-(void)showSliderContentWithDuration:(NSTimeInterval)time
{
    _isShown = YES;
    _positionConstraint.constant = 0.0;
    
    [UIView animateWithDuration:time delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^
    {
        _settingsOutsideView.alpha = 1.0;
        [self.superview layoutIfNeeded];
    }
    completion:^(BOOL finished)
    {
        [_viewController viewDidAppear:YES];
    }];
}

-(void)hideSliderContentWithDuration:(NSTimeInterval)time
{
    _isShown = NO;
    _positionConstraint.constant = _sliderLength;
    
    [UIView animateWithDuration:time delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^
    {
        _settingsOutsideView.alpha = 0.0;
        self.layer.shadowOpacity = 0.0;
        [self.superview layoutIfNeeded];
    }
    completion:^(BOOL finished)
    {
        [_viewController viewDidDisappear:YES];
    }];
}

-(void)panDragButton:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint translation = [gestureRecognizer translationInView:self.superview];
    if([gestureRecognizer state] == UIGestureRecognizerStateBegan ||
       [gestureRecognizer state] == UIGestureRecognizerStateChanged) {
        CGFloat delta = _positionConstraint.constant + translation.x;
        delta = MAX(0, MIN(_sliderLength, delta));
        
        CGFloat level =(_sliderLength - delta) / _sliderLength;
        _settingsOutsideView.alpha = 1.0 * level;
        
        [gestureRecognizer setTranslation:CGPointZero inView:self.superview];
        _positionConstraint.constant = delta;
        [self layoutIfNeeded];
        [_dragButton layoutIfNeeded];
        
    } else if([gestureRecognizer state] == UIGestureRecognizerStateEnded) {
        CGRect screenRect = [[UIScreen mainScreen] bounds];
        CGFloat screenWidth = MAX(screenRect.size.width, screenRect.size.height);
        CGFloat position = _sliderLength - (screenWidth - self.frame.origin.x);

        const CGFloat kSwitchAtPullPercentage = .1;
        CGFloat threshold = _sliderLength * (_isShown ? kSwitchAtPullPercentage : 1 - kSwitchAtPullPercentage);
        if(position > threshold) {
            [self hideSliderContentWithDuration:_animationDuration * ((_sliderLength - position) / _sliderLength)];
        } else {
            [self showSliderContentWithDuration:_animationDuration * (position / _sliderLength)];
        }
    }
}


-(void)outsideTapped:(UIPanGestureRecognizer *)gestureRecognizer {
    [self hideSliderContent];
}

@end
